<template>
    <el-select ref="treeSelect" :value="valueTitle" v-bind="selectOptions"
               :loading="loading"
               @clear="clearHandle" style="width: 100%;">
        <el-option :value="valueTitle" :label="valueTitle"
                   class="options" v-if="showTree">
            <custom-el-tree ref="$CustomSelectTree" v-bind="treeOptions"
                            @node-click="handleNodeClick"/>
        </el-option>
    </el-select>
</template>

<script>
import {ElTree, genProps} from "../attributes";
import { ElSelect } from "../../form/Dynamic/attributes";

export default {
    name: 'TreeSelect',
    components: {
        CustomElTree: () => import('../ElTree'),
    },
    model: {
        prop: 'value',
        event: 'changeValue',
    },
    props: {
        // 初始值
        value: {
            type: String,
            default: null
        },
        // select配置项
        selectProps: {
            type: Object,
            default() {
                return {};
            },
        },
        // 树配置项
        treeProps: {
            type: Object,
            default() {
                return {};
            },
        },
        // 选项列表数据(树形结构的对象数组)
        options: {
            type: Array,
            default: () => []
        },
        // 可清空选项
        clearable: {
            type: Boolean,
            default: true,
        },
        // 自动收起
        accordion: {
            type: Boolean,
            default: true,
        },
        // 展开所有
        expandAll: {
            type: Boolean,
            default: false,
        },
        // 是否禁用
        disabled: {
            type: Boolean,
            default: false
        },
        // 是否选择叶子节点
        selectLeaf: {
            type: Boolean,
            default: false,
        },
        placeholder: {
            type: String,
            default: '请选择',
        },
    },
    data () {
        return {
            query: null,
            valueId: null,
            valueTitle: '',
            defaultExpandedKey: [],
            treeData: [],
            loading: false,
            currentNodeKey: null,
        }
    },
    computed: {
        selectOptions () {
            let props = genProps(ElSelect, this.selectProps);
            props.filterable = true;
            props.filterMethod = this.filterMethod;
            props.disabled = this.disabled;
            props.clearable = this.clearable;
            props.popperClass = 'tree_select_popper';
            delete props.listenerEvent;
            delete props.slots;
            return props;
        },
        treeOptions () {
            let props = genProps(ElTree, this.treeProps);
            props.accordion = this.accordion;
            props.defaultExpandAll = this.expandAll;
            props.filterNodeMethod = this.filterNodeMethod;
            props.currentNodeKey = this.valueId;
            props.data = this.treeData;
            delete props.listenerEvent;
            delete props.slots;
            return props;
        },
        showLabel() {
            return this.selectProps.label || 'label';
        },
        showTree() {
            return this.$utils.isNotEmptyList(this.treeOptions.data);
        },
    },
    watch: {
        value: {
            handler () {
                this.init();
            },
            deep: true,
            immediate: true,
        },
        options: {
            handler () {
                this.init();
            },
            deep: true,
        },
        query: {
            handler () {
                this.$refs.$CustomSelectTree.filter(this.query);
            },
            deep: true,
        },
    },
    mounted() {
        this.getData();
    },
    methods: {
        init () {
            const _this = this;
            this.query = null;
            if (!_this.$utils.isNotEmpty(_this.selectProps.remote)) {
                let treeData = this.options.map(item => $.extend({}, item));
                if (typeof _this.treeProps.procData === 'function') {
                    treeData = _this.treeProps.procData.call(_this, treeData);
                }
                this.treeData = treeData;
            }
            setTimeout(() => {
                _this.initHandle();
            }, _this.$refs.$CustomSelectTree ? 0 : 100);
        },
        // 初始化值
        initHandle () {
            const _this = this;
            this.valueId = this.value;
            if (this.valueId) {
                this.defaultExpandedKey = [this.valueId]; // 设置默认展开
                this.$emit('changeValue', this.valueId);
            }
            this.$nextTick(() => {
                if (_this.valueId && _this.$refs.$CustomSelectTree) {
                    let node = _this.$refs.$CustomSelectTree.getNode(_this.valueId);
                    if (node) {
                        _this.valueTitle = node.data[_this.treeOptions.props.label]; // 初始化显示
                        _this.$refs.$CustomSelectTree.setCurrentKey(_this.valueId); // 设置默认选中
                    }
                }
            });
        },
        filterMethod (query) {
            this.query = query;
        },
        filterNodeMethod (value, data) {
            if (!value) {
                return true;
            }
            return data[this.treeOptions.props.label].indexOf(value) !== - 1;
        },
        getData() {
            const _this = this;
            if (!_this.$utils.isNotEmpty(_this.selectProps.remote)) {
                return;
            }
            let queryData = $.extend({}, (_this.selectProps.query || {}));
            return _this.fetchData(_this.selectProps.remote, queryData).then(result => {
                let resData = result.data || [];
                if (typeof _this.treeProps.procData === 'function') {
                    resData = _this.treeProps.procData.call(_this, resData);
                }
                _this.treeData = resData;
                _this.loading = false;
                _this.initHandle();
            }).catch(() => {
            });
        },
        // 切换选项
        handleNodeClick (data) {
            if (this.selectLeaf && this.$utils.isNotEmptyList(data[this.treeOptions.props.children])) {
                if (this.$refs.$CustomSelectTree) {
                    this.$refs.$CustomSelectTree.setCurrentKey(this.valueId);
                }
                return;
            }
            this.valueTitle = data[this.showLabel];
            this.valueId = data[this.treeOptions.nodeKey];
            this.$emit('changeValue', this.valueId);
            this.$emit('change', this.valueId, data);
            this.defaultExpandedKey = [];
            this.$refs['treeSelect'].blur();
            this.dispatch('ElFormItem', 'el.form.change', data);
        },
        // 清除选中
        clearHandle () {
            this.valueTitle = '';
            this.valueId = null;
            this.defaultExpandedKey = [];
            this.clearSelected();
            this.$emit('changeValue', null);
            this.$emit('change', null);
            this.dispatch('ElFormItem', 'el.form.change', null);
        },
        // 清空选中样式
        clearSelected () {
            if (this.$refs.$CustomSelectTree) {
                let currentNode = $(this.$refs.$CustomSelectTree.$el).find('.el-tree-node.is-current');
                if (currentNode && currentNode.length > 0) {
                    $(currentNode).removeClass('is-current');
                }
            }
        },
        setExpandedKey (value) {
            this.defaultExpandedKey = value;
        },
        getNode (value) {
            if (this.$refs.$CustomSelectTree) {
                return this.$refs.$CustomSelectTree.getNode(value);
            }
            return undefined;
        },
    },
}
</script>

<style scoped>
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
    height: auto;
    padding: 0;
    overflow: hidden;
    overflow-y: auto;
}

.el-select-dropdown__item.selected {
    font-weight: normal;
}

ul li >>> .el-tree .el-tree-node__content {
    height: auto;
    padding: 0 20px;
}

.el-tree-node__label {
    font-weight: normal;
}

.el-tree >>> .is-current .el-tree-node__label {
    color: red;
    font-weight: 700;
}

.el-tree >>> .is-current .el-tree-node__children .el-tree-node__label {
    color: #606266;
    font-weight: normal;
}
</style>
